#include "AudioSource.h"
#include "WavFile.h"
#include "OggFile.h"

using namespace fxcc;

AudioSource::AudioSource(const Desc& desc)
    :m_Desc(desc)
{
    m_Available = Init();
    
}

bool AudioSource::Init()
{
    switch (m_Desc.m_Type)
    {
    case Desc::Type::_Wav_:
        return InitWav();

        case Desc::Type::_Ogg_:
            return InitOgg();


        default:
        break;
    }
}

bool AudioSource::InitWav()
{
    WavFile wavFile(m_Desc.m_WavPath);
    if (wavFile.m_Available)
    {
        Create();
        BufferData(wavFile.GetAlFormat(), (const short*)wavFile.Data(), wavFile.DataSize(), wavFile.SampleRate());
    }

    return wavFile.m_Available;

}

bool AudioSource::InitOgg()
{
    OggFile oggFile(m_Desc.m_OggPath);

    if (oggFile.m_Available)
    {
        Create();
        BufferData(oggFile.GetAlFormat(), oggFile.Data(), oggFile.DataSize(), oggFile.SampleRate());
    }
    return true;
}

void AudioSource::Create()
{
    alGenSources(1, &m_Source);
    alGenBuffers(1, &m_Buffer);
}

void AudioSource::BufferData(int format, const short* data, int size, int freq)
{
    // Fill the m_Buffer with audio data
    alBufferData(m_Buffer, format, data, size, freq);
    // Associate the m_Buffer with the m_Source
    alSourcei(m_Source, AL_BUFFER, m_Buffer);
}

void AudioSource::Play()
{
    // Play the sound
    alSourcePlay(m_Source);
}

void AudioSource::Pause()
{
    alSourcePause(m_Source);
}

void AudioSource::Stop()
{
    alSourceStop(m_Source);

}
void AudioSource::WaitEnd()
{
    while (GetState() == AL_PLAYING);
}

int AudioSource::GetInt(int param)
{
    int res = 0;
    alGetSourcei(m_Source, param, &res);
    return res;
}

int AudioSource::GetState()
{
    return this->GetInt(AL_SOURCE_STATE);
}

float AudioSource::GetFloat(int param)
{
    float res = 0.0f;
    alGetSourcef(m_Source, param, &res);
    return res;
}

void AudioSource::SetInt(int param, int value)
{
    alSourcei(m_Source, param, value);
}

void AudioSource::SetFloat(int param, float value)
{
    alSourcef(m_Source, param, value);

}

float AudioSource::GetGain()
{
    return GetFloat(AL_GAIN);
}

void AudioSource::SetGain(float gain)
{
    SetFloat(AL_GAIN, gain);
}

void AudioSource::SetVec3(int param, float x, float y, float z)
{
    alSource3f(m_Source, param, x, y, z);
}

void AudioSource::GetVec3(int param, float& x, float& y, float& z)
{
    alGetSource3f(m_Source, param, &x, &y, &z);

}

void AudioSource::SetIVec3(int param, int x, int y, int z)
{
    alSource3i(m_Source, param, x, y, z);
}

void AudioSource::GetIVec3(int param, int& x, int& y, int& z)
{
    alGetSource3i(m_Source, param, &x, &y, &z);
}

void AudioSource::Delete()
{
    alDeleteSources(1, &m_Source);
    alDeleteBuffers(1, &m_Buffer);
}

AudioSource::~AudioSource()
{
    Delete();
}